1

转载
Go基础学习记录 - 编写Web应用程序 - 安全验证

安全验证

前面加了很多功能,但是程序存在严重的安全漏洞,用户可以访问在服务器上读/写的任意路径。
为了缓解这种情况,我们可以编写一个函数来使用正则表达式验证标题。
首先,将"regexp"添加到导入列表中。
然后我们可以创建一个全局变量来存储我们的验证表达式:

var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$")

函数regexp.MustCompile将解析并编译正则表达式,并返回一个regexp.Regexp。
MustCompile与Compile的区别在于,如果表达式编译失败,它将会出现异常,而Compile会将错误作为第二个参数返回。
现在,让我们编写一个函数,该函数使用validPath表达式来验证路径并提取页面标题

func getTitle(w http.ResponseWriter, r *http.Request) (string, error) {
    m := validPath.FindStringSubmatch(r.URL.Path)
    if m == nil {
        http.NotFound(w, r)
        return "", errors.New("无效的页面标题")
    }

    return m[2], nil // 标题是第二个子表达式中
}

如果标题有效,它将与nil错误值一起返回。
如果标题无效,该函数将向HTTP连接写入“404 Not Found”错误,并向处理程序返回错误。
要创建新错误,我们必须导入错误包。
下面在每个处理程序中调用getTitle:

func viewHandler(w http.ResponseWriter, r *http.Request) {
    title, err := getTitle(w, r)
    if err != nil {
        return
    }

    p, err := loadPage(title)
    if err != nil {
        http.Redirect(w, r, "/edit/"+title, http.StatusFound)
        return
    }

    renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, r *http.Request) {
    title, err := getTitle(w, r)
    if err != nil {
        return
    }

    p, err := loadPage(title)
    if err != nil {
        p = &Page{Title: title}
    }

    renderTemplate(w, "edit", p)
}

func saveHandler(w http.ResponseWriter, r *http.Request) {
    title, err := getTitle(w, r)
    if err != nil {
        return
    }

    body := r.FormValue("body")
    p := &Page{
        Title: title,
        Body:  []byte(body),
    }

    err = p.save()

    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }

    http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

修改完之后,重新编译并运行程序,当访问非edit、view、save路由时,会出现异常错误提示


唐三叔叔
93 声望13 粉丝

Hi,说到做到这是我的忍道